﻿#region Includes
using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using GingerGL;
using GingerGL.Math;
#endregion

namespace GingerGL.Graphics
{
    //------------------------------------------------------------//
    /// <summary>
    /// Scene Camera
    /// </summary>
    public abstract class Camera : Frustum
    {
        //--------------------------------------------------------//
        #region Properties
        /// <summary>
        /// Gets Camera Position
        /// </summary>
        public Vector3 Position { get; protected set; }
        /// <summary>
        /// Gets Camera Target Vector
        /// </summary>
        public Vector3 View { get; protected set; }
        /// <summary>
        /// Gets Camera Up Vector
        /// </summary>
        public Vector3 UpVector { get; protected set; }
        /// <summary>
        /// Gets Aspect Ratio
        /// </summary>
        public Viewport Viewport { get; private set; }
        #endregion
        //--------------------------------------------------------//
        #region Constructors
        /// <summary>
        /// Camera Structure
        /// </summary>
        protected Camera()
        {
            this.Position = Vector3.Zero;
            this.Viewport = Viewport.Default;
            this.Position = new Vector3(0, 0, 0);
            this.View = new Vector3(0, 0, 1);
            this.UpVector = new Vector3(0, 1, 0);
        }
        /// <summary>
        /// Camera Structure
        /// </summary>
        public Camera(Vector3 position, Vector3 target, Vector3 up) : this()
        {
            this.Position = position;
            this.View = target;
            this.UpVector = up;
        }
        #endregion
        //--------------------------------------------------------//
        #region Methods
        /// <summary>
        /// Moves Camera Forward and Backward
        /// </summary>
        public abstract void MoveForward(float speed);
        /// <summary>
        /// Moves Camera Left and Right
        /// </summary>
        public abstract void MoveRight(float speed);
        /// <summary>
        /// Moves Camera Up and Down
        /// </summary>
        public abstract void MoveUp(float speed);
        /// <summary>
        /// Moves Camera Position
        /// </summary>
        public abstract void Set(Vector3 pos);
        /// <summary>
        /// Update Camera to Screen
        /// </summary>
        public abstract void Update();
        /// <summary>
        /// Sets OpenGL Perspective
        /// </summary>
        public void SetPersective()
        {
            Matrix4 ProjectionMatrix = Matrix4.CreatePerspectiveFieldOfView(
                MathHelper.DegreesToRadians(this.Viewport.FieldOfView), 
                this.Viewport.AspectRatio, 
                this.Viewport.NearClipdistance, 
                this.Viewport.FarClipDistance);
            // Select The Projection Matrix
            GL.MatrixMode(MatrixMode.Projection);
            //reset matrix
            GL.LoadIdentity();
            //Apply the projection matrix
            GL.LoadMatrix(ref ProjectionMatrix);
            // Select The Modelview Matrix
            GL.MatrixMode(MatrixMode.Modelview);
            // Reset The Modelview Matrix
            GL.LoadIdentity();
        }
        /// <summary>
        /// Resize Window
        /// </summary>
        public void Resize(int width, int height)
        {
            this.Viewport.AspectRatio = (float)width / (float)height;
            SetPersective();
        }
        #endregion
        //--------------------------------------------------------//
    }
    //------------------------------------------------------------//
}
